using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace ihm
{
    public class WinReceive
    {
        //Liste des messages reçus (comme une BAL)
        List<Message> listMessageRecu;

        //Thread permettant le traitement des messages reçus
        System.Threading.Thread threadReceiver;

        //Fenetre principale, pour pouvoir demander la modification de controles
        CIAI fenetrePrincipale;

        public WinReceive(CIAI c)
        {
            this.fenetrePrincipale = c;
            this.listMessageRecu = new List<Message>();
            threadReceiver = new Thread(this.ReceiverTask);
            //Attacher le handler à l'événement messageRecu
        }

        //Ajouter un nouveau message aux messages reçus
        public void ajouterMessageRecu(String message)
        {
            Message messFormatted = new Message(message);
            this.listMessageRecu.Add(messFormatted);
        }

        //Démarrer la tâche
        public void StartReceiver()
        {
            threadReceiver.Start();
        }

        //Eteindre la tâche
        public void StopReceiver()
        {
            try
            {
                threadReceiver.Abort();
            }
            catch
            {

            }
        }


        //Code de la tâche
        public void ReceiverTask()
        {
            while (true)
            {
                if (this.listMessageRecu.Count > 0)
                {
                    Message messageEnTraitement = this.listMessageRecu[0];
                    traiterMessage(messageEnTraitement);
                    this.listMessageRecu.Remove(messageEnTraitement);
                }
            }
        }

        //Traitement des messages
        //Le code est assez gros, mais l'algorithme est trivial
        //La fonction Invoke permet de faire une demande à la fenêtre principale de modification asynchrone sur ses controles
        public void traiterMessage(Message mess)
        {
            if (mess.Type == Message.TypeMessage.Erreur)
            {
                ErreurMachine err = null;
                if (mess.Message_t == "arreturgent" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                {
                    err = new ErreurMachine(ErreurMachine.TypeErreur.ArretUrgence);
                    fenetrePrincipale.Invoke(fenetrePrincipale.objetARepareDelegate, new object[] { err });
                }
                else if (mess.Message_t == "panne")
                {
                    if (mess.TypeObjet_t == Message.TypeObjet.Imprimante)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.ImprimantePanne);
                    if (mess.TypeObjet_t == Message.TypeObjet.CapteurArriveePiece)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveePiecePanne);
                    if (mess.TypeObjet_t == Message.TypeObjet.CapteurArriveeCarton)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveeCartonPanne);
                    if (mess.TypeObjet_t == Message.TypeObjet.CapteurArriveePalette)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveePalettePanne);
                    if (mess.TypeObjet_t == Message.TypeObjet.MiseEnPalette)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.MiseEnPaletteBloquee);
                    if (mess.TypeObjet_t == Message.TypeObjet.Carton)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.TauxRebutEleve);
                    if (mess.TypeObjet_t == Message.TypeObjet.Plastifieur)
                        err = new ErreurMachine(ErreurMachine.TypeErreur.PlastifieusePanne);
                    if(mess.TypeObjet_t != Message.TypeObjet.Lot && mess.TypeObjet_t!=Message.TypeObjet.Carton && mess.TypeObjet_t != Message.TypeObjet.Commande)
                        fenetrePrincipale.Invoke(fenetrePrincipale.objetARepareDelegate, new object[] {err});
                }
                else if (mess.TypeObjet_t == Message.TypeObjet.Commande && mess.Message_t == "impossible")
                {
                    fenetrePrincipale.Invoke(fenetrePrincipale.changementEtatExpeditionDelegate, new object[] { mess.IdObjet, Expedition.EtatExpedition.NonDisponible });
                }
                else
                {
                    Console.Out.WriteLine("Erreur impossible à traiter...");
                }
            }
            else if (mess.Type == Message.TypeMessage.Information)
            {
                if (mess.TypeObjet_t == Message.TypeObjet.Lot)
                {
                    if (mess.Message_t == "debut")
                    {
                        fenetrePrincipale.Invoke(fenetrePrincipale.changementEtatCommandeDelegate, new object[] { mess.IdObjet, Commande.EtatCommande.EnCours });
                        WriteLog(mess);
                    }
                    if (mess.Message_t == "fin")
                    {
                        fenetrePrincipale.Invoke(fenetrePrincipale.changementEtatCommandeDelegate, new object[] { mess.IdObjet, Commande.EtatCommande.Termine });
                        WriteLog(mess);
                    }
                }
                else
                    WriteLog(mess);
            }
            else if (mess.Type == Message.TypeMessage.Reponse)
            {
                if (mess.Message_t == "repare" || mess.Message_t == "arreturgent")
                {
                    ErreurMachine newErr = null;
                    if (mess.TypeObjet_t != Message.TypeObjet.Lot && mess.TypeObjet_t != Message.TypeObjet.Carton && mess.TypeObjet_t != Message.TypeObjet.Commande)
                    {
                        switch (mess.TypeObjet_t)
                        {
                            case Message.TypeObjet.SystemeGlobal:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.ArretUrgence) });
                                break;
                            case Message.TypeObjet.Imprimante:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.ImprimantePanne) });
                                break;
                            case Message.TypeObjet.CapteurArriveePiece:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveePiecePanne) });
                                break;
                            case Message.TypeObjet.CapteurArriveeCarton:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveeCartonPanne) });
                                break;
                            case Message.TypeObjet.CapteurArriveePalette:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.CapteurArriveePalettePanne) });
                                break;
                            case Message.TypeObjet.MiseEnPalette:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.MiseEnPaletteBloquee) });
                                break;
                            case Message.TypeObjet.Carton:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.TauxRebutEleve) });
                                break;
                            case Message.TypeObjet.Plastifieur:
                                fenetrePrincipale.Invoke(fenetrePrincipale.objetRepareDelegate, new object[] { new ErreurMachine(ErreurMachine.TypeErreur.PlastifieusePanne) });
                                break;
                        }
                    }
                }
                else if (mess.Message_t == "demarrage" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                {
                    fenetrePrincipale.Invoke(fenetrePrincipale.manageButtonOnDemarrageDelegate, new object[] { });
                } 
                else if (mess.Message_t == "arret" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                {
                    fenetrePrincipale.Invoke(fenetrePrincipale.manageButtonOnArretDelegate, new object[] { });
                }
                else if (mess.TypeObjet_t == Message.TypeObjet.Commande)
                {
                    if (mess.Message_t.ToLower() == "envoye")
                    {
                        fenetrePrincipale.Invoke(fenetrePrincipale.changementEtatExpeditionDelegate, new object[] { mess.IdObjet, Expedition.EtatExpedition.Prete });
                    }
                }
                WriteLog(mess); 
            }
        }

        //Ecrire un message dans le log
        public void WriteLog(Message mess)
        {
            string logToWrite = null;
            if (mess.Type == Message.TypeMessage.Reponse)
            {
                if (mess.Message_t == "demarrage" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                    logToWrite = "Atelier démarré";
                else if (mess.Message_t == "arret" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                    logToWrite = "Atelier arrêté";
                else if (mess.Message_t == "arreturgent" && mess.TypeObjet_t == Message.TypeObjet.SystemeGlobal)
                    logToWrite = "Atelier urgent traîté";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.Imprimante)
                    logToWrite = "Imprimante réparée";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.CapteurArriveePiece)
                    logToWrite = "Arrivée pièce réparé";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.CapteurArriveeCarton)
                    logToWrite = "Arrivée carton réparé";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.CapteurArriveePalette)
                    logToWrite = "Arrivée palette réparé";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.MiseEnPalette)
                    logToWrite = "Atelier mise en palette débloqué";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.Carton)
                    logToWrite = "Taux de rebut réglé";
                else if (mess.Message_t == "repare" && mess.TypeObjet_t == Message.TypeObjet.Plastifieur)
                    logToWrite = "Machine plastifieuse réparée";
                else if (mess.Message_t == "envoye" && mess.TypeObjet_t == Message.TypeObjet.Commande && mess.IdObjet != -1)
                {
                    logToWrite = "Commande n°" + mess.IdObjet + " expédiée";
                }
            }
            else if (mess.Type == Message.TypeMessage.Information)
            {
                if (mess.TypeObjet_t == Message.TypeObjet.Carton)
                {
                    if (mess.Message_t.Contains("imprime"))
                    {
                        try
                        {
                            String id = mess.Message_t.Split(' ')[1];
                            logToWrite = "Carton imprimé, taux de rebus = " + id;
                        }
                        catch { }
                    }
                }
                else if (mess.TypeObjet_t == Message.TypeObjet.Palette)
                {
                    logToWrite = "Palette n°" + mess.IdObjet + " stockée";
                }
                else if (mess.TypeObjet_t == Message.TypeObjet.Lot)
                {
                    if (mess.Message_t == "debut") logToWrite = "Debut du lot n°";
                    else if (mess.Message_t == "reprise") logToWrite = "Reprise du lot n°";
                    else if (mess.Message_t == "interruption") logToWrite = "Interruption du lot n°";
                    else if (mess.Message_t == "fin") logToWrite = "Fin du lot n°";
                    logToWrite += mess.IdObjet;
                }
            }
            else
                logToWrite = "Message incompréhensible: " + mess.getFormattedNetworkMessage();

            this.fenetrePrincipale.Invoke(fenetrePrincipale.ajoutLogDelegate, new object[] { logToWrite, mess.Date });
        }
    }
}
